package com.marktotop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.marktotop.entity.business.Vaccinator;
import com.marktotop.entity.system.*;
import com.marktotop.enums.UserStatusEnum;
import com.marktotop.enums.UserTypeEnum;
import com.marktotop.error.SystemCodeEnum;
import com.marktotop.error.SystemException;
import com.marktotop.mapper.*;
import com.marktotop.response.ResultBean;
import com.marktotop.response.ResultCode;
import com.marktotop.service.IDepartmentService;
import com.marktotop.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.marktotop.util.JWTUtils;
import com.marktotop.shiro.JwtToken;
import com.marktotop.util.MD5Utils;
import com.marktotop.vo.system.*;
import jdk.nashorn.internal.ir.CallNode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author MarkToTop
 * @since 2021-07-12
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private IDepartmentService departmentService;



    /**
     * 用户登录
     *
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @Override
    public String login(String username, String password) throws SystemException{
        String token;
        // 根据用户名查询用户
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if (user != null) {
            String salt = user.getSalt();
            //秘钥为盐
            String target = MD5Utils.md5Encryption(password, salt);
            //生成Token
            token = JWTUtils.sign(username, target);

            JwtToken jwtToken = new JwtToken(token);
            try {
                SecurityUtils.getSubject().login(jwtToken);
            } catch (AuthenticationException e) {
                throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,e.getMessage());
            }
        } else {
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"登录用户不存在，请查证后重试！");
        }
        return token;
    }


    /**
     * 查询用户角色
     * @param id 用户ID
     * @return
     */
    @Override
    public List<Role> findRolesById(Long id) throws SystemException {
        User dbUser = userMapper.selectById(id);
        if(dbUser == null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该用户不存在");
        }
        List<Role> roles=new ArrayList<>();
        // 根据角色id查询相应的roles集合
        List<UserRole> userRoleList = userRoleMapper.selectList(new QueryWrapper<UserRole>().eq("user_id",dbUser.getId()));
        List<Long> rids=new ArrayList<>();
        if(!CollectionUtils.isEmpty(userRoleList)){
            for (UserRole userRole : userRoleList) {
                rids.add(userRole.getRoleId());
            }
            if(!CollectionUtils.isEmpty(rids)){
                for (Long rid : rids) {
                    Role role = roleMapper.selectById(rid);
                    if(role!=null){
                        roles.add(role);
                    }
                }
            }
        }
        return roles;
    }


    /**
     * 查询权限
     *
     * @param roles 用户的角色
     * @return
     */
    @Override
    public List<Menu> findMenuByRoles(List<Role> roles) {
        List<Menu> menus=new ArrayList<>();
        if(!CollectionUtils.isEmpty(roles)){
            //存放用户的菜单id
            Set<Long> menuIds = new HashSet<>();
            List<RoleMenu> roleMenus;
            for (Role role : roles) {
                //根据角色ID查询权限ID
                roleMenus= roleMenuMapper.selectList(new QueryWrapper<RoleMenu>().eq("role_id",role.getId()));
                if(!CollectionUtils.isEmpty(roleMenus)){
                    for (RoleMenu roleMenu : roleMenus) {
                        menuIds.add(roleMenu.getMenuId());
                    }
                }
            }
            if(!CollectionUtils.isEmpty(menuIds)){
                for (Long menuId : menuIds) {
                    //该用户所有的菜单
                    Menu menu = menuMapper.selectById(menuId);
                    if(menu!=null){
                        menus.add(menu);
                    }
                }
            }
        }
        return menus;
    }


    /**
     * 添加用户
     * @param userVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addUser(UserVO userVO) throws SystemException {
        @NotBlank(message = "用户名不能为空") String username = userVO.getUsername();
        @NotNull(message = "部门id不能为空") Long departmentId = userVO.getDepartmentId();
        // 根据 用户名查询 是否存在用户
        Integer count = userMapper.selectCount(new QueryWrapper<User>().eq("username", username));
        if(count != 0){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该用户名已被占用");
        }
        // 查询部门，判断部门是否为空
        Department department = departmentService.getById(departmentId);
        if(department==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该部门不存在");
        }
        User user = new User();
        // 利用反射机制对JavaBean的属性进行处理
        BeanUtils.copyProperties(userVO,user);
        String salt=UUID.randomUUID().toString().substring(0,32);
        user.setPassword(MD5Utils.md5Encryption(user.getPassword(), salt))
                .setModifyTime(new Date())
                .setCreateTime(new Date())
                .setSalt(salt)
                // 添加的用户默认是普通用户
                .setType(UserTypeEnum.SYSTEM_USER.getTypeCode())
                // 添加的用户默认启用
                .setStatus(UserStatusEnum.AVAILABLE.getStatusCode())
                .setAvatar("http://image.biaobaiju.com/uploads/20180830/21/1535637285-fguYEdoqkQ.jpg");
        // 保存 信息
        if (userMapper.insert(user) == 0){
            return false;
        }
        return true;
    }


    /**
     * 查询用户信息
     *
     * @return
     */
    @Override
    public UserInfoVO info() throws SystemException {
        ActiveUserVO activeUser = (ActiveUserVO) SecurityUtils.getSubject().getPrincipal();
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setAvatar(activeUser.getUser().getAvatar());
        userInfoVO.setUsername(activeUser.getUser().getUsername());
        userInfoVO.setUrl(activeUser.getUrls());
        userInfoVO.setNickname(activeUser.getUser().getNickname());
        List<String> roleNames = activeUser.getRoles().stream().map(Role::getRoleName).collect(Collectors.toList());
        userInfoVO.setRoles(roleNames);
        userInfoVO.setPerms(activeUser.getPermissions());
        userInfoVO.setIsAdmin(activeUser.getUser().getType()==UserTypeEnum.SYSTEM_ADMIN.getTypeCode());
        DepartmentVO dept = departmentService.editDept(activeUser.getUser().getDepartmentId());
        if(dept != null){
            userInfoVO.setDepartment(dept.getName());
        }
        return userInfoVO;
    }


    /**
     * 分配角色
     *
     * @param id 用户id
     * @param rids 角色数组
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignRoles(Long id, Long[] rids) throws SystemException {
        //删除之前用户的所有角色
        User user = userMapper.selectById(id);
        if(user == null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"用户不存在");
        }
        userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id",user.getId()));
        //增加现在分配的
        if(rids.length > 0){
            for (Long rid : rids) {
                Role role = roleMapper.selectById(rid);
                if(role == null){
                    throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"roleId="+rid+",该角色不存在");
                }
                //判断角色状态
                if(role.getStatus() == 0){
                    throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"roleName="+role.getRoleName()+",该角色已禁用");
                }
                UserRole userRole = new UserRole();
                userRole.setUserId(id);
                userRole.setRoleId(rid);
                userRoleMapper.insert(userRole);
            }
        }
        return true;
    }


    /**
     * 用户拥有的角色ID
     * @param id 用户id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<Long> roles(Long id) throws SystemException {
        User user = userMapper.selectById(id);
        if(user == null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该用户不存在");
        }
        List<UserRole> userRoleList = userRoleMapper.selectList(new QueryWrapper<UserRole>().eq("user_id", user.getId()));
        List<Long> roleIds=new ArrayList<>();
        if(!CollectionUtils.isEmpty(userRoleList)){
            for (UserRole userRole : userRoleList) {
                Role role = roleMapper.selectById(userRole.getRoleId());
                if(role != null){
                    roleIds.add(role.getId());
                }
            }
        }
        return roleIds;
    }


    /**
     * 更新用户状态信息
     *
     * @param id
     * @param status
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateStatus(Long id, Boolean status) throws SystemException {
        User dbUser = userMapper.selectById(id);
        if(dbUser==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"要更新状态的用户不存在");
        }
        // 判断是否更新当前用户
        ActiveUserVO activeUser = (ActiveUserVO) SecurityUtils.getSubject().getPrincipal();
        if(dbUser.getId().equals(activeUser.getUser().getId())){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"无法改变当前用户状态...");
        }else {
            User t = new User();
            t.setId(id);
            t.setStatus(status ?UserStatusEnum.AVAILABLE.getStatusCode() :
                    UserStatusEnum.DISABLE.getStatusCode());
            // 按主键选择性更新
            userMapper.updateById(t);
            return true;
        }
    }


    /**
     * 用户列表(分页展示)
     *
     * @param pageNum
     * @param pageSize
     * @param userVO
     * @return
     */
    @Override
    public ResultBean findUserList(Integer pageNum, Integer pageSize, UserVO userVO) {
        // 开启分页
        Page<UserVO> page = new Page<>(pageNum,pageSize);
        IPage<UserVO> usersByPage = userMapper.getUsersByPage(page,userVO);
        if (usersByPage.getRecords().isEmpty()){
            return ResultBean.result(ResultCode.NON_RESULT);
        }
        return ResultBean.ok().message("获取用户信息成功！")
                .data("total",usersByPage.getTotal())
                .data("userList",usersByPage.getRecords());
    }


    /**
     * 根据id删除用户
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUser(Long id) throws SystemException {
        User user = userMapper.selectById(id);
        ActiveUserVO activeUser = (ActiveUserVO) SecurityUtils.getSubject().getPrincipal();
        if(user==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"要删除的用户不存在");
        }
        if(user.getId().equals(activeUser.getUser().getId())){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"不能删除当前登入用户");
        }

        if (userMapper.deleteById(id) == 0){
            return false;
        }
        //删除对应[用户-角色]记录
        userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id",user.getId()));
        return true;
    }


    /**
     * 更新用户信息
     *
     * @param id
     * @param userEditVO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(Long id, UserEditVO userEditVO) throws SystemException {
        User dbUser = userMapper.selectById(id);
        @NotBlank(message = "用户名不能为空") String username = userEditVO.getUsername();
        @NotNull(message = "部门不能为空") Long departmentId = userEditVO.getDepartmentId();
        if(dbUser==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"要删除的用户不存在");
        }
        Department department = departmentService.getById(departmentId);
        if(department==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该部门不存在");
        }
        List<User> users = userMapper.selectList(new QueryWrapper<User>().eq("username", username));
        if(!CollectionUtils.isEmpty(users)){
            if(!users.get(0).getId().equals(id)){
                throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"该用户名已被占用...");
            }
        }
        User user = new User();
        BeanUtils.copyProperties(userEditVO,user);
        user.setModifyTime(new Date())
                .setId(dbUser.getId());
        userMapper.updateById(user);
        return true;
    }



    /**
     * 编辑
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserEditVO editUser(Long id) throws SystemException {
        User user = userMapper.selectById(id);
        if(user==null){
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,"要编辑的用户不存在");
        }
        UserEditVO userEditVO = new UserEditVO();
        BeanUtils.copyProperties(user,userEditVO);
        Department department = departmentService.getById(user.getDepartmentId());
        if(department!=null){
            userEditVO.setDepartmentId(department.getId());
        }
        return userEditVO;
    }

    /**
     * 判断部门中是否有用户
     * @return
     */
    @Override
    public boolean findUserByDept(Long id) {
        if (userMapper.getUserByDept(id) != 0){
            return false;
        }
        return true;
    }

    /**
     * 获取所有用户，作为联系人使用
     *
     * @return
     */
    @Override
    public List<UserContactVO> findUserForContact() {
        return userMapper.getAllUser();
    }

    /**
     * 用户列表，供其他调用(不分页)
     *
     * @return
     * @throws SystemException
     */
    @Override
    public List<UserContactVO> selectAllUserContact() throws SystemException {
        List<UserContactVO> users = userMapper.findAllUserContact(UserTypeEnum.SYSTEM_USER.getTypeCode());
        if (users.isEmpty()) {
            throw new SystemException(SystemCodeEnum.PARAMETER_ERROR, "用户信息列表为空，不能继续...");
        }
        return users;
    }
}
